package me.helllp.dake.generator.parser;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.expr.SimpleName;
import com.github.javaparser.utils.ParserCollectionStrategy;
import com.github.javaparser.utils.ProjectRoot;
import com.github.javaparser.utils.SourceRoot;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class JavaParserUtil {
    public static void main(String[] args) throws FileNotFoundException {
//        String path = "E:\\work\\smartCode\\core\\src\\main\\java";
//        parseProject(path);

        String filePath = "E:\\work\\smartCode\\core\\src\\main\\java\\me\\helllp\\smart\\core\\SmartInterface.java";
        ParseResult<CompilationUnit> cu = new JavaParser().parse(new File(filePath));
        NodeList<Modifier> list = new NodeList<>();
        list.add(Modifier.publicModifier());
        CompilationUnit unit = cu.getResult().get();

        NodeList<TypeDeclaration<?>> types = unit.getTypes();
        for (TypeDeclaration<?> type : types) {
            FieldDeclaration field = new FieldDeclaration();
            field.setModifiers(Modifier.Keyword.PRIVATE);
            field.setBlockComment("这是一个属性测试");
//            field.setData();
            // 变量
            field.setVariables(new NodeList<>());
            VariableDeclarator declarator = new VariableDeclarator();
            declarator.setName("test");
            declarator.setType(String.class);
            field.getVariables().add(declarator);


            type.addMember(field);
        }

//        unit.getTypes().addLast(type);
        System.out.println(unit);
        parseOneFile(cu.getResult().get());
//        SourceRoot root = new SourceRoot();
    }

    /**
     * 解析工程下的所有Java文件
     *
     * @param path 工程根目录
     */
    public static void parseProject(String path) {
        Path root = Paths.get(path);
        // only parsing
        ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root);
        projectRoot.getSourceRoots().forEach(sourceRoot -> {
            System.out.println(sourceRoot);
            try {
                // 解析source root
                sourceRoot.tryToParse();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 获取解析后的编译单元列表
            List<CompilationUnit> cuList = sourceRoot.getCompilationUnits();
            cuList.forEach(JavaParserUtil::parseOneFile);
        });
    }

    /**
     * 解析单个Java文件
     *
     * @param cu 编译单元
     */
    public static void parseOneFile(CompilationUnit cu) {
        // 类型声明
        NodeList<TypeDeclaration<?>> types = cu.getTypes();
        for (TypeDeclaration<?> type : types) {
            System.out.println("## " + type.getName());
            // 成员
            NodeList<BodyDeclaration<?>> members = type.getMembers();
            members.forEach(JavaParserUtil::processNode);
        }
    }

    /**
     * 处理类型,方法,成员
     *
     * @param node
     */
    public static void processNode(Node node) {
        if (node instanceof TypeDeclaration) {
            // 类型声明
            // do something with this type declaration

        } else if (node instanceof MethodDeclaration) {
            // 方法声明
            // do something with this method declaration
            String methodName = ((MethodDeclaration) node).getName().getIdentifier();
            System.out.println("方法: " + methodName);

        } else if (node instanceof FieldDeclaration) {
            // 成员变量声明
            // do something with this field declaration
            // 注释
            Comment comment = node.getComment().orElse(null);

            // 变量
            NodeList<VariableDeclarator> variables = ((FieldDeclaration) node).getVariables();
            SimpleName fieldName = variables.get(0).getName();
            if (comment != null) {
                System.out.print(comment.getContent());

            }
            System.out.print("\t");
            System.out.print(fieldName);
            System.out.println();
        }

        for (Node child : node.getChildNodes()) {
            processNode(child);
        }
    }

}
